<script setup lang="ts">
import type { Ref } from 'vue'
import type { CodeMateField, CodeMateMethod, CodeMateModel, CodeMateType } from '@/apis/code/codeMateApi'
import type { DataAction } from '@/components/DataForm/types'
import { omit } from 'lodash-es'
import { inject, onMounted, reactive, ref } from 'vue'
import { codeMateFieldApi, codeMateModelApi } from '@/apis/code/codeMateApi'
import { useTable } from '@/components/DataPage/useTable'
import CodeFieldTypeSelect from './CodeFieldTypeSelect.vue'
import CodeFieldTypeValue from './CodeFieldTypeValue.vue'
import { codeDictFieldFields, codeEntityFieldFields } from './codeMate'

const { parentType, parent, data } = defineProps<{
  parentType: CodeMateType
  parent: Partial<CodeMateMethod> | Partial<CodeMateModel>
  data: CodeMateField[]
}>()

const primaryFieldId = ref<number>()
onMounted(() => {
  if (parentType === 'model' && parent.type === 'ENTITY') {
    primaryFieldId.value = parent.primaryFieldId
  }
})

const isDictType = parentType === 'model' && parent.type === 'DICT'

const fieldTitle = parentType === 'model' ? (isDictType ? '字典项' : '字段') : '参数'

const {
  Table,
  tableData,
  openRowEdit,
  openRowEditAll,
  submitRowEditAll,
  cancelRowEditAll,
} = useTable<undefined, CodeMateField>({
  data,
  tableFields: isDictType
    ? codeDictFieldFields
    : codeEntityFieldFields.filter(f => f.name !== 'queryType' ? true : (parentType === 'method' && (parent.type === 'LIST_QUERY' || parent.type === 'PAGE_QUERY'))),
})

const api = codeMateFieldApi
const rowEditNum = ref(0)

const loadProjectData = inject<() => Promise<void>>('loadProjectData')
async function rowSubmitSuccess() {
  loadProjectData && await loadProjectData();
  (tableData.value as CodeMateField[]).sort((a, b) => a.priority - b.priority)
}

const actions = reactive<Record<string, DataAction>>({
  modify: {
    label: '编辑',
    type: 'primary',
    authCode: 'code:mate:module:modify',
    click: async (_: any, index?: number) => await openRowEdit(index!, api.modify),
  },
  primaryKey: {
    label: row => row.id === primaryFieldId.value ? '取消主键' : '设为主键',
    type: row => row.id === primaryFieldId.value ? 'warning' : 'success',
    authCode: 'code:mate:module:modify',
    click: async (row: any) => {
      const primaryId = (row.id === primaryFieldId.value) ? -1 : row.id
      await codeMateModelApi.modify({ id: parent.id, primaryFieldId: primaryId })
      primaryFieldId.value = primaryId
      loadProjectData && await loadProjectData()
    },
    show: () => parentType === 'model' && parent.type === 'ENTITY',
    message: true,
  },
  remove: {
    label: '删除',
    type: 'danger',
    authCode: 'code:mate:project:remove',
    confirm: '删除不可恢复，请谨慎确认',
    click: data => api.remove(data.id),
    success: async (_: any, index?: number) => {
      (tableData.value as any[]).splice(index!, 1)
      loadProjectData && await loadProjectData()
    },
    message: true,
  },
})

const models = inject<Ref<CodeMateModel[]>>('models')

function importModel() {
  const method = parent as CodeMateMethod
  const model = models?.value?.find(m => m.id === method.parentId)
  if (model === undefined)
    return

  const tableFields = tableData.value as CodeMateField[]
  for (const field of model.fieldList) {
    if (tableFields.filter(f => f.name === field.name).length === 0) {
      const omitFields = ['id', 'parentId', 'priority']
      if (field.id === model.primaryFieldId && method.type === 'CREATE_CMD') {
        continue
      }
      if (method.type.endsWith('QUERY')) {
        omitFields.push('required')
      }
      openRowEdit(tableFields.length, api.create, {
        ...omit(field, ...omitFields),
        parentId: parent.id,
        priority: tableFields.length + 1,
      })
    }
  }
}

function addField(index: number) {
  if ((tableData.value as CodeMateField[]).length === 0 && parent.type === 'ENTITY') {
    openRowEdit(index, api.create, { parentId: parent.id, priority: index + 1, type: 'INTEGER', name: 'id', remark: '主键', required: true })
  }
  else {
    openRowEdit(index, api.create, { parentId: parent.id, priority: index + 1, type: 'STRING', length: 32 })
  }
}
</script>

<template>
  <el-divider content-position="left">
    {{ fieldTitle }}列表
  </el-divider>
  <div class="flex flex-row flex-justify-end">
    <el-button v-if="parentType === 'method'" type="primary" @click="importModel">
      导入模型参数
    </el-button>

    <el-button v-if=" (tableData as CodeMateField[]).length > 0 " type="primary" @click="openRowEditAll(api.modify)">
      编辑全部
    </el-button>
    <el-button type="primary" @click="() => addField(0)">
      {{ `添加${fieldTitle}` }}
    </el-button>
  </div>
  <Table
    class="mt-2" :row-actions="[actions.primaryKey, actions.modify, actions.remove]"
    @row-submit-success="rowSubmitSuccess"
    @row-edit-change="(indexList:number[]) => rowEditNum = indexList.length"
  >
    <template #type="{ row }">
      <CodeFieldTypeValue v-model:type="row.type" v-model:model-id="row.modelId" v-model:is-list="row.isList" />
    </template>
    <template #edit_type="{ row }">
      <CodeFieldTypeSelect v-model:type="row.type" v-model:model-id="row.modelId" v-model:is-list="row.isList" />
    </template>
  </Table>
  <div class="mt-2 flex flex-row flex-justify-end">
    <el-button v-if=" (tableData as CodeMateField[]).length > 0 && rowEditNum > 0 " type="primary" @click="submitRowEditAll">
      保存全部
    </el-button>
    <el-button v-if=" (tableData as CodeMateField[]).length > 0 && rowEditNum > 0" @click="cancelRowEditAll">
      取消全部
    </el-button>
    <el-button type="primary" @click="() => addField((tableData as CodeMateField[]).length ?? 0)">
      {{ `添加${fieldTitle}` }}
    </el-button>
  </div>
</template>
